home *** CD-ROM | disk | FTP | other *** search
- // Bookburro Ajax Panel for GreaseMonkey and Turnabout
- // @version 0.18
- /*
-
- (C) 2005 Johan Sundstr├╢m (0.13 .. 0.18)
- License: Creative Commons "Attribution-ShareAlike 2.0"
- http://creativecommons.org/licenses/by-sa/2.0/
-
- Skeletal parts of DOM-Drag by Aaron Boodman, 2001
- http://www.youngpup.net/2001/domdrag
- License: Creative Commons "Attribution-ShareAlike 2.0"
- http://creativecommons.org/licenses/by-sa/2.0/
-
- (C) 2005 Reify (0.11r .. 0.12r)
- License: Creative Commons "Attribution-ShareAlike 1.0"
- http://creativecommons.org/licenses/by-sa/1.0/
-
- (C) 2005 Jesse Andrews, Britt Selvitelle under cc-by-sa (0.01 .. 0.11)
- License: Creative Commons "Attribution-ShareAlike 1.0"
- http://creativecommons.org/licenses/by-sa/1.0/
-
- Snipits used from RSS Reader for GreaseMonkey
- http://www.xs4all.nl/~jlpoutre/BoT/Javascript/RSSpanel/
- Version: 1.03 (C) 2005 Johannes la Poutre
- THANKS!
-
- Changelog:
-
- * 2006-01-09 *
-
- 0.18 - Added bookpool.com, contributed by Pallando.
-
- * 2005-11-02 *
-
- 0.17 - Added Google Print. Initial preparations for ISBN-13, for Jan. 1, 2007.
-
- * 2005-10-04 *
-
- 0.16 - Bugfix for Greasemonkey 0.53 -- for now, only open/close/drag the title
-
- * 2005-10-03 *
-
- 0.15 - Added BiggerBooks.com, Bookbyte, Booksamillion.com and eCampus.com
-
- * 2005-10-02 *
-
- 0.14 - Made the bookburro window draggable
- - Added (one hour) price cache for last seen book
- - Added Abebooks, Alibris, biblio.com, cdon.com, exlibris.se and libris.se
- - Centralized all (functionally important) code dealing with each store
- - Integrated my improvements with the Reified version 0.12r codebase
- - Added option to update book URL when fetching price tag
- / Johan Sundstr├╢m, oyasumi+bookburro@gmail.com
-
- * 2005-09-19 *
-
- 0.13 - GreaseMonkey 0.6 compatibility fix to get working onclick handlers
- - Added AJAX fetching from Powell's Books, figuring they want customers
- - Added adlibris.se, akademibokhandeln.se, bokus.com and internetbokhandeln.se
- - For kicks, added availability listing at Link├╢ping University library
- / Johan Sundstr├╢m, oyasumi+bookburro@gmail.com
-
- * 2005-06-24 *
-
- 0.12x - Added support for alldirect.com
-
- * 2005-06-21 *
-
- 0.12r - works when injected before the page has finished loading; fixed price-parsing on Powells.com; removed Powells from list in the Burro box
-
- 0.11r - modified by Reify to work in Internet Explorer with Turnabout:
- - The price wouldn't render on Amazon for some reason, so we now render with DIVs + SPANs
- - Set style in a way that works in IE (element.setAttribute("style", str) doesn't work in IE)
- - Moved data: URIs to one place to make the script easier to read
- - Show/hide the price table rather than changing the box's dimensions to make code easier to maintain (don't have dimensions scattered throughout)
- - Anchored top right icons to the top right instead of top left so their position will update automatically if the box has to be wider
- - Branch to use MS or Mozilla XML parser
-
- * 2005-04-25 *
-
- 0.11 - improved skin & add link to message if no results
- 0.10 - bug fix - don't show iframes!
- 0.09 - bug fix - alert were out of scope, plus a couple visual tweaks
- 0.08 - bug - use (function(){ code })(); so you don't kill other javascript
- 0.07 - use AWS to grab amazon's prices
-
- * 2005-04-24 *
- 0.06 - wasn't checking for ISBN= in the url as well!
- 0.05 - added Amazon marketplace
- 0.04 - worked on skin to make it PURTY
- 0.03 - use AJAX to add the prices
- 0.02 - Improved interface
- 0.01 - initial releasea
-
- */
-
- // ==UserScript==
- // @name Book Burro - Remixing the bookstore
- // @namespace http://overstimulate.com/userscripts/
- // @description Compare book prices from various book stores
- // @include http://amazon.com/*
- // @include http://www.amazon.com/*
- // @include http://www.powells.com/*
- // @include http://half.ebay.com/*
- // @include http://buy.com/*
- // @include http://www.buy.com/*
- // @include http://biblio.com/*
- // @include http://www.biblio.com/*
- // @include http://search.barnesandnoble.com/*
- // @include http://barnesandnoble.com/*
- // @include http://www.barnesandnoble.com/*
- // @include http://www.alldirect.com/*
- // @include http://www.bokus.com/*
- // @include http://www.internetbokhandeln.se/*
- // @include http://www.akademibokhandeln.se/*
- // @include http://akademibokhandeln.se/*
- // @include http://www.adlibris.se/*
- // @include http://*.bibl.liu.se/*
- // @include http://www.cdon.com/*
- // @include http://www.exlibris.se/*
- // @include http://www.libris.se/*
- // @include http://www.alibris.com/*
- // @include http://bookbyte.com/*
- // @include http://www.bookbyte.com/*
- // @include http://biggerbooks.com/*
- // @include http://www.biggerbooks.com/*
- // @include http://ecampus.com/*
- // @include http://www.ecampus.com/*
- // @include http://www.booksamillion.com/*
- // @include http://print.google.com/*
- // @include http://www.bookpool.com/*
- // @include http://bookpool.com/*
- // ==/UserScript==
-
- var debug = 0;
-
- // You are welcome either to put your own affiliate codes and dev keys below,
- // or to leave them as is, sponsoring further development of this application
- var abebooks_aid = 10395338, abebooks_pid = 1814912;
- var amazon_associate_code = 'diaryohayou-20';
- var amazon_dev_key = '05GK2S0SFN8G8P5KY482';
- var bn_associate_code = 41532291;
- var half_associate_code = 1814912; // (CJ PID, really -- not your CJ account number!)
-
- // Of these, only name, id and bookURL are mandatory (but hostname, getISBN, ajaxURL and ajaxPrice are usually needed too).
- // name: book store name listed in burro window
- // id: a short unique id string for all document nodes related to this book store
- // hostname: a hostname regexp used to determine whether to look for ISBNs on this page
- // bookURL: address to link the name to, %s being replaced with the ISBN of the book
- // getISBN: function run on book store pages to find the book ISBN it's about; returns false (no book), or an ISBN string
- // -- or -- regexp applied to the full URL of the page, whose first matched paren pair gives the ISBN of the book shown
- // -- defaults to /isbn[\/=]([0-9X]{10})(&|\?|\.|$)/i if omitted
- // ajaxURL: address to pick up price for the book whose ISBN is %s, for ajax handler (defaults to bookURL, if not given)
- // ajaxData: '' by default; if given, the data to provide with the ajax request body, %s replaced with the ISBN of the book
- // ajaxMethod: POST by default (if not given); which HTTP method to access the above
- // ajaxHeaders: HTTP headers for the AJAX request. Adds a Content-Type: 'application/x-www-form-urlencoded' header for all
- // POST requests missing a content-type declaration.
- // ajaxPrice: function run on fetched AJAX page to get book price; returns false (not found) or a price and currency string
- // or an associative array from store id to price and currency string, when one AJAX request can get many prices
- // -- or -- regexp (or string form, the latter mostly useful avoid quoting /:s) whose first paren picks up the book price
- // -- or -- false, in which case no xmlHTTPRequest is ever made (for instance because some other handler finds the price)
- // priceFix: if ajaxPrice was a string and this function is provided, the resulting price is fed through the callback
- // updateURL: if provided, a function run on the fetched AJAX page, to get a new (or proper) URL for the book link
- var handlers = [
- { name: 'Abebooks.com', id: 'abebooks', hostname: /\babebooks.com$/i, getISBN: /(?:isbn|bi)=([0-9X]{10})(&|\?|$)/i,
- bookURL: 'http://www.abebooks.com/servlet/SearchResults?isbn=%s&pid='+ abebooks_pid +'&aid='+ abebooks_aid,
- ajaxPrice: /<span class="price">\D*(\$[^<]*)/i },
- { name: 'Ad Libris', id: 'alse', hostname: /\badlibris\.se$/i,
- bookURL: 'http://www.adlibris.se/shop/product.asp?isbn=%s',
- ajaxMethod: 'GET',
- ajaxPrice: function( html, http )
- {
- if( html.match( 'Ingen titel med detta ISBN finns hos AdLibris.' ) )
- return '';
- //return SEK( html.match( '<span class="price">([^<]*)<' )[1] );
- return html.match('class="price">([^<]*)<' )[1];
- } },
- /*
- { name: 'Akademibokhandeln', id: 'abse', hostname: /\bakademibokhandeln\.se$/i,
- getISBN: nextSameTagAfter( 'td', '^ISBN' ),
- updateURL: firstLinkTo( 'cc_artikel.visa_artikelkort', 'http://www.akademibokhandeln.se/db/caweb/' ),
- bookURL: 'http://www.akademibokhandeln.se/db/caweb/sok.avanc_artiklar?mtitel=exact&cisbn=%s',
- ajaxPrice: /<span class="pris">\s*([^<]*)</i, priceFix: SEK },
-
- { name: 'Alibris', id: 'alibris', hostname: /\balibris\.com$/i,
- getISBN: nextTagAfter( 'b', 'ISBN:' ),
- bookURL: 'http://www.alibris.com/search/search.cfm', ajaxData: 'S=R&qisbn=%s',
- updateURL: firstLinkTo( '/search/detail.cfm?', 'http://www.alibris.com' ),
- ajaxPrice: /<span class="red-price"><b>([^<]*)</i },
- { name: 'AllDirect.com', id:'alldirect', hostname: /\balldirect\.com$/i,
- getISBN: nextTagAfter( 'b', 'ISBN:' ),
- bookURL: 'http://www.alldirect.com/book.asp?&isbn=%s',
- ajaxPrice: 'All Direct\x27s[^P]*Price[^\$]*([^<]*)<' },
- */
- { name: 'Amazon', id: 'amazon', hostname: /\bamazon\.com$/i,
- getISBN: function() {
- if( location.href.match( 'rate-this' ) ) return;
- return location.href.match( /\/([0-9X]{10})(\/|\?|$)/i )[1];
- },
- bookURL: 'http://www.amazon.com/exec/obidos/ASIN/%s/'+ amazon_associate_code,
- ajaxURL: 'http://xml.amazon.com/onca/xml3?t='+ amazon_associate_code +'&dev-t='+ amazon_dev_key +'&type=lite&f=xml&mode=books&AsinSearch=%s',
- ajaxPrice: function( html, http )
- {
- var xml = str2xml( html );
- var our = xml.getElementsByTagName( 'OurPrice' );
- var used = xml.getElementsByTagName( 'UsedPrice' );
- return { amazon: our.length && our[0].childNodes[0].nodeValue || '',
- amazon_used: used.length && used[0].childNodes[0].nodeValue || '' };
- } },
-
- { name: 'Amazon (used)', id: 'amazon_used', ajaxPrice: false,
- bookURL: 'http://www.amazon.com/exec/obidos/redirect?tag='+ amazon_associate_code +'&path=tg/stores/offering/list/-/%s/all/' },
- /*
- { name: 'Barnes & Noble', id: 'bn', hostname: /\bbarnesandnoble\.com$/i,
- bookURL: 'http://service.bfast.com/bfast/click?bfmid=2181&sourceid='+ bn_associate_code +'&bfpid=%s&bfmtype=book',
- ajaxURL: 'http://search.barnesandnoble.com/booksearch/isbninquiry.asp?isbn=%s',
- ajaxPrice: 'priceRightBNPrice[^>]*>([^<]*)</' },
- */
- { name: 'BestPrices.com', id: 'bestprices', hostname: /\bbestprices\.com$/i,
- bookURL: 'http://www.bestprices.com/cgi-bin/vlink/' + bn_associate_code,
- getISBN: function() {
- return location.href.match( /vlink\/(.*)/i )[1];
- },
- ajaxURL: 'http://www.bestprices.com/cgi-bin/vlink/%s',
- ajaxPrice: /Our Price:[^\$]*([^<]*)</,
- ajaxMethod: 'GET'
- },
-
- { name: 'Biblio.com', id: 'biblio', hostname: /\bbiblio\.com$/i,
- bookURL: 'http://www.biblio.com/isbn/%s.html', ajaxMethod: 'GET',
- //ajaxPrice: /<div[^>]*>\s*((?:$|$)\S+)\s*</i
- ajaxPrice: /<div[^>]*>\s*$([^<]*)/i
- },
-
- { name: 'BiggerBooks.com', id: 'biggerbooks', hostname: /\bbiggerbooks\.com$/i,
- bookURL: 'http://www.dpbolvw.net/click-'+ half_associate_code +'-9467039?ISBN=%s',
- ajaxURL: 'http://www.biggerbooks.com/bk_detail.asp?ISBN=%s', ajaxMethod: 'GET',
- //ajaxPrice: /<span class='price'>([^<]+)/
- ajaxPrice: /Our Price <span class='price'>([^<]+)/
- },
- /*
- { name: 'Bokus.com', id: 'bokus', hostname: /\bbokus\.com$/i,
- getISBN:/(?:\/|FAST_VALUE=ISBN&FAST=|ISBN=)([0-9X]{10})(\.html)?(\?|&|$)/i,
- bookURL: 'http://www.bokus.com/b/%s.html',
- ajaxURL: 'http://www.bokus.com/cgi-bin/book_search.cgi?FAST_VALUE=ISBN&FAST=%s',
- ajaxPrice: '<span class="price"[^>]*>([^<]*)<', ajaxMethod: 'GET'
- //, priceFix: SEK
- },
- */
- { name: 'Bookbyte', id: 'bookbyte_new', hostname: /\bbookbyte\.com$/i,
- //getISBN: function(){ return document.getElementById('lbIsbn').textContent; },
- bookURL: 'http://www.kqzyfj.com/click-'+ half_associate_code +
- '-10365617?url=http%3A%2F%2Fwww.bookbyte.com%2Fproduct.aspx%3Fisbn%3D%s',
- ajaxURL: 'http://www.bookbyte.com/product.aspx?isbn=%s',
- ajaxMethod: 'GET',
- /*
- ajaxPrice: function( html, http ) {
- var prices = { bookbyte_new: html.match( '<span id="lbNewPrice">(?:<[^>]*>)*([^<]*)' ),
- bookbyte_used: html.match( '<span id="lbUsedPrice">(?:<[^>]*>)*([^<]*)' ),
- bookbyte_bazaar: html.match( '<a href="#Bazaar_Bookmark" class=price-red-14>([^<]*)' ) }, i;
- for( i in prices )
- prices[i] = prices[i] ? unHTML( prices[i][1] ).replace( /[^$.0-9]/g, '' ) : '';
- return prices;
- }
- */
- ajaxPrice: '<span id="ctl00_ContentPlaceHolder1_lbNewPrice">New <a class="one"[^>]*>([^<]*)<'
- },
- /*
- { name: 'Bookbyte (used)', id: 'bookbyte_used', ajaxPrice: false, bookURL: 'http://www.kqzyfj.com/click-'+
- half_associate_code +'-10365617?url=http%3A%2F%2Fwww.bookbyte.com%2Fproduct.aspx%3Fisbn%3D%s' },
- { name: 'Bookbyte (bazaar)', id: 'bookbyte_bazaar', ajaxPrice: false, bookURL: 'http://www.kqzyfj.com/click-'+
- half_associate_code +'-10365617?url=http%3A%2F%2Fwww.bookbyte.com%2Fproduct.aspx%3Fisbn%3D%s' },
- */
- { name: 'Bookpool.com', id: 'bookpool', hostname: /\bbookpool.com$/i,
- getISBN: /(?:qs|is|sm)[\/=]([0-9X]{10})(&|\?|\.|$)/i,
- bookURL: 'http://www.bookpool.com/sm/%s',
- ajaxPrice: /Our\s+Price:?(?:<[^>]*>\s*)*([^<]+)/i },
- { name: 'Booksamillion.com', id: 'bamm', hostname: /\bbooksamillion\.com$/i,
- bookURL: 'http://www.dpbolvw.net/click-'+ half_associate_code +'-42121?isbn=%s', // /<B>Our\s+Price:\s*([^<]+)/i
- ajaxURL: 'http://www.booksamillion.com/ncom/books?type=isbn&find=%s', ajaxMethod: 'GET',
- ajaxPrice: function( html, http ){ return '$' + html.match( /Our\s+Price:\s*\$?([^<]+)/i )[1]; } },
- { name: 'Buy.com', id: 'buy', hostname: /\bbuy\.com$/i,
- getISBN: function(){
- var s = document.title.match( /ISBN ([0-9X]{10}) -/i )[1];
- if(!s) s = document.title.match( /ISBN ([0-9]{13}) -/i )[1];
- return s;
- },
- bookURL: 'http://www.buy.com/retail/GlobalSearchAction.asp?qu=%s',
- //ajaxPrice: 'productPrice[^>]*>([^<]*)</'
- ajaxPrice: 'Our Price:[^\$]*([^<]*)</'
- },
- /*
- { name: 'CDON.com', id: 'cdon', hostname: /\bcdon\.com$/i,
- getISBN: nextSameTagAfter( 'td', 'ISBN:' ), updateURL: function( html, http ) {
- return 'http://www.cdon.com/' + unHTML(html.match( /<a href=.(product\.phtml\?prod=\d+)/ )[1]);
- }, bookURL: 'http://www.cdon.com/search_result.phtml?ed_search_value=%s&sl_search_field=books_isbn',
- ajaxPrice: '<td[^>]* class=\'priceMedium\'[^>]*>([^<]*)<', ajaxMethod: 'GET', priceFix: SEK },
- */
- { name: 'eCampus.com', id: 'ecampus', hostname: /\becampus.com$/i,
- bookURL: 'http://www.anrdoezrs.net/click-'+ half_associate_code +'-5029466?ISBN=%s',
- ajaxURL: 'http://www.ecampus.com/bk_detail.asp?ISBN=%s',
- ajaxMethod: 'GET',
- //ajaxPrice: /Our\s+Price\s*<font[^>]*>([^<]+)/i
- ajaxPrice: /New Price[^\$]*([^<]*)</i
- },
- /*
- { name: 'Ex Libris', id: 'exlibris', hostname: /\bexlibris\.se$/i,
- getISBN: nextSameTagAfter( 'span', 'ISBN:' ), updateURL: function( html, http ) {
- return 'http://www.exlibris.se/' + unHTML(html.match( '<form [^>]* action="([^"]*)' )[1]);
- }, bookURL: 'http://www.exlibris.se/advancedsearch.aspx?%s', ajaxMethod: 'GET',
- ajaxURL: 'http://www.exlibris.se/searchresult.aspx?TYPE=Simple&SEARCH_FIELD=2&SEARCH_FIELD_TEXT=ISBN&SEARCH_VALUE=%s&SHOW_IMAGES=true',
- ajaxPrice: /<span id="ctrlProductDetails_lblPrice">([^<]+)</, priceFix: SEK
- },
-
- { name: 'Google Print', id: 'googleprint', hostname: /print\.google\.com$/i,
- bookURL: 'http://print.google.com/print?as_isbn=%s',
- getISBN: function() {
- var re = new RegExp( 'https?://www.google.com/pagead/ads\\?.*' +
- '&channel=[^&]*BTB-ISBN:([0-9X]{10})', 'i' );
- return firstDocumentLinkMatching( re, 1 );
- }, updateURL: firstLinkTo( 'http://print.google.com/print?', '' ),
- ajaxPrice: function( html, http ) {
- var re = new RegExp( '<a(?:[^>]*) href=["\']?' +
- 'https?://print.google.com/print\\?' +
- '[^"\']*&sig=', 'i' );
- return html.match( re ) != null;
- } },
- { name: 'Half.com', id: 'half', hostname: /\bhalf\.ebay\.com$/i,
- getISBN: nextTagAfter( 'b', 'ISBN:' ),
- bookURL: 'http://www.kqzyfj.com/click-'+ half_associate_code +'-1932276?ISBN=%s',
- ajaxURL: 'http://half.ebay.com/search/search.jsp?product=books:isbn&query=%s',
- ajaxPrice: 'Best[^P]*Price[^$]*([^<]*)<' },
-
- { name: 'Internetbokhandeln', id: 'ibse', hostname: /\binternetbokhandeln\.se$/i,
- getISBN: /(?:\/bok|&s_search=)([0-9Xx]{10})(\.html)?(\?|$)/, updateURL: function( html, http )
- {
- return 'http://www.internetbokhandeln.se' + unHTML(html.match('<a href="?(/[^"]*FIXME/bok[0-9xX]{10}\\.html)')[1]);
- }, bookURL: 'http://www.internetbokhandeln.se/_114K3FPUVX/msearchres.html?s_sortby=b&s_media=ALL&s_type=i&s_search=%s',
- ajaxMethod: 'GET', ajaxPrice: '<span class=price>([^<]*)<', priceFix: SEK },
-
- { name: 'Libris Media', id: 'librismedia', hostname: /\blibris\.se$/i,
- getISBN: function(){ return document.body.innerHTML.match( /<span class=[^>]*>\s*ISBN ([0-9X]{10})/mi )[1]; },
- updateURL: firstLinkTo( 'Browse_Item_Details.asp', 'http://www.libris.se/stores_app/' ),
- bookURL: 'http://www.libris.se/stores_app/Browse_dept_items.asp?Store_id=102&fran=sok',
- ajaxData: 'SEARCH_SKU=%s&SEARCH_DEPT=-1&Search_Store.x=36&Search_Store.y=7',
- ajaxPrice: [/<span class="normal2">Pris:.*?<span[^>]*>(\d+)(,\d\d)? *kr</mi,
- /<b>\s*Libris l\345gpris (\d+)(,\d\d)? *kr/mi,
- /<span class="fakta">\s*(\d+)(,\d\d)? *kr/mi], priceFix: SEK },
- { name: 'LiU Library', id: 'liubibl', hostname: /\bbibl\.liu\.se$/i,
- getISBN: nextSameTagAfter( 'a', 'ISBN/ISSN:' ),
- bookURL: 'http://hip.bibl.liu.se/ipac20/ipac.jsp?menu=search&index=ISBN&term=%s',
- ajaxPrice: function( html, http )
- {
- var book, inne = 0, ute = 0;
- while( book = /<tr height="15">(.*?)<\/tr>/gi.exec( html ) )
- if( !book[1].match( /referens/i ) )
- if( book[1].match( /tillg|reserverad/i ) )
- inne++;
- else
- ute++;
- if( inne+ute )
- {
- html = inne;
- if( ute )
- return html + ' (of '+(inne+ute)+')';
- return html + ' in';
- }
- } },
- */
- { name: 'Powell\'s Books', id: 'powells', hostname: /\bpowells.com$/i,
- /*
- getISBN: function()
- {
- var dt = document.getElementsByTagName( 'dt' ), i;
- for( i=0; i<dt.length; i++ )
- if( dt[i].innerHTML.match( 'ISBN:' ) &&
- checkISBN( dt[i].nextSibling.title ) )
- return dt[i].nextSibling.title;
- },
- getISBN: function()
- {
- return location.href.match( /isbn=(.*)/i )[1]);
- },
- */
- //http://www.powells.com/cgi-bin/biblio?inkey=18-9780545010221-0
- //http://www.powells.com/cgi-bin/biblio?isbn=0596008732
- getISBN: function()
- {
- return location.href.match(/inkey=[^\-]*-([^\-]*)-/)[1] ||
- location.href.match(/isbn=(.*)/)[1] ||
- location.href.match(/ISBN=(.*)/)[1];
- },
- bookURL: 'http://www.powells.com/cgi-bin/biblio?isbn=%s',
- ajaxPrice: '<div class="price">([^<]*)<'
- }
- ];
-
- var hasFetched = false;
- var Icons =
- {
- title: 'data:image/gif;base64,R0lGODlheAAOAOYAAAAAAOmUUUOGfx1eVj8/M1ijnqBhLrmFVv//zNi6oCUIAO/vwJqEbGk4EL+/mm9vWZmZmVpaWvfAl7ydiC8vJo+PcwAPCaJtSylNS////4tCC9/fs0MeAa+vjefy9LR1QpnMzH9/Zny3s7WIazttbG5MMVyVj09PQJ+fgMvO11UwEwMWGq10R5K6ugg2Nh8fGdiecOaxhdiKTAAACZlqPnWtqu/dxTxlYXNeS1o6IU8rEZqytlp2d4p4bDZ/dn+Eh4pWL2JNOFKLhf/frtusjtGFS750N8ulfo1qVM/Ppm2HhsSQa615UvSlYy5HS9rb1hAEDqdvPjgpJg8PDP/vx4S2s6toMzRERKmlmrS8vkFfXwAhHnI7Ek06K+3x8D92c6/M0DNmZk5nb4xNGr+8s9uNT8x9OysRAtSniJWOlq6GYwAICZGtsP+4dGVCLkaVj4GpqF9fTMuLW8q/ra1rOV1UTXpKJmaZmb+SabGzstWXZEtMTmg9G4RZN4rFwVZeYSH5BAUUAAgALAAAAAB4AA4AAAf/gAiCg4MzM4SIgyo5hGcKj1JTiZOUlZaXmJmagmtrPEprlRN9TA0ICjpIaiMjSEhdm7Gys7SInXd3JiQ3oZN8Bx9jXGpoaEtLFzRumkkEKLTNz4nRtbWGbHBVJttCJBaTDQYaYzASSzAHQCxEmw4AIbTu8Iny1bMzWTtwcH4Fbz4DBHhLZGfMmCJy5NCwY0qWuwdxCHQYVIHAiYmCkkR8sABBvQ4hkgx6GBFjCGknPYYkUCGEgwcnNix4QCCOyEsrVoBpUUOEvwIAw4T5RkjFmA8faPDhU8sdgAcUADhA8ODpCQATN0yhEGKrx3coAMQh5BSqVAQACAhKiyAEgCnv/94CAICAwpQQdjdcmiFmRQuf/nwICDMAA4ZeCLrouBClMR8VJUrMcjd2A4CYlwVNeYEgDgCRFQCgcHdVLVmxCCyfQGuardvVaD8jCFsBQRLUllY40eICRA0BwL8I7ZRhUA8VNAx8sIOGSoISy2LVYz2dAF3rguQ5xT3y3Vq1bFm3PSt+/NTyliyIwbAFhB+BJIinKC5oAh8WBqzAoEKFA5ISONTxRwqZPITAApfdNhYCL0hylV60uUNBVedl99SBmYXnGnnhhfaMapmsgYEY7bWwxRoZZJBCGlAMMgEQdMhghR5DxKAADWokYMMTWeyBiTtTdODZM3Z1EBo8HYjlgL9dC8izwBSmWRjkkAhMMeWG54WnFQUOeFbhJWtoocWJHqj4gyGE6MBCGQHIUIQZetBwAB5qBEGGF3n8KNYLFx541RQPDIICnxSIVE9Y0nwVB5+BzgbXCRSo5VaWUSYR1QuJhniFBRlkAQEAiA1yBgtFtNGEEUbQYUAUeKDBABYZPBGBPbTWWs1cP4BKyRk06NFEAKdawUIUTBBhgxfI+mjrssxiMpclXdhBRxlmmJEUDTQckcAcXnjwRKPNhltrIAA7',
- about: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAuJAAALiQE3ycutAAAAB3RJTUUH1QQYCDkprC+64gAAAOdJREFUKM+FkrFOAkEURc9ddrJZCgsqCwtCIiUFJa2df2CwNXRS8AmGisLEaGGs3VhTYDUtxZaED/AriGHjPhuEDC5wq3l5czL3vjeyzBlHtC6KoI4BuPk8Qqx3549rov3+YPBIp3NHq3VLlnkkBf0AWK2+6fevWCze8H7CaPRKUfzgnKsG0jSh272kLEuWyy/a7QvSNKnIsJEk6vWE2SxnPH5nOn3YWopjh9VqIbDBGA5fyPNnGo2znZVIEEWhJTNDgmbzfHvZzA6H/pP3k3/TqQQkIYle7z6oT74wnz8d3KNOfY19/QKFiTrWqbiPtAAAAABJRU5ErkJggg==',
- carrotRight: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QQYCR020Q08hgAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAAAiklEQVQY07XPIQoCURSF4e8NAzYxGicNuAa1WlyCO3AlZnfiNgwahQFxikkcBIsGfaZpzgODJ/4c/nMvPyR8g7EsephgH6q6aXnWIelhjkUsi0EL88TqFUfMYlnscMoS5wUccMYS4yxhfuGNPho88oQ5xxQjrHHpKkcMccMqVPU99eATG2zb4n/zAS4OHrV1hIB/AAAAAElFTkSuQmCC',
- carrotDown: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QQYCRoeq/kCuwAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAAAmElEQVQY083QMUoDARSE4W92U2xhkxSpAgY0AXMQ29zCM3iSXEXQTrCws44Im85CkO1jnq2KKQWnGxiY+Yd/oXw1tTrr7D86CYdD5Xk3HA8vTi8la7xW1T5Jg8IEN6PvPXnEAkOa5l5Viwuc4yk/d9VyfoLrqnpIMmCGu2z79/wGUsv5FFcYY5Nt/wKjI+BvuEWnbfu///kTargo75QVC5oAAAAASUVORK5CYII=',
- close: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAuJAAALiQE3ycutAAAAB3RJTUUH1QQYCDcSg6d+SAAAAPBJREFUKM+Fkr1qAkEURs9dnWBrJT5IHkEw4gtEsBQs/AlpkiKlJGnEJlqIjRbrPoAQYhPio1hGsPAHFoW5KSIxo7J7qvlgDty534j6Rolgt987OQnA7XuEsTuegwIeMYiIkx2hVnsjCL7+su9/0mz2Lox0oNOpUiw+kc2mUVWGww8mkxYiYK09F4xJMho9kMs9IiJMpy8Y83vFWkUTCVcAWCxWLJcrRIT1OiSTOczuCXieK2y3IeXyK4PBPZtNSKn0zGzWJpW6uvyGer1LpVIgn78GYD7/ptHo0e/fHbemvtHIHv4zvonv4ayXuK9xyg8qt0tfe9qKPAAAAABJRU5ErkJggg=='
- };
-
- function quoteRegExp( re )
- {
- return re.replace( /([.*+^$?(){}\[\]\\])/g, '\\$1' );
- }
-
- function regexpify( stringOrRegExp, flags, quote )
- {
- if( (typeof stringOrRegExp == 'function') && stringOrRegExp.exec )
- return stringOrRegExp;
- if( quote ) stringOrRegExp = quoteRegExp( stringOrRegExp );
- return new RegExp( stringOrRegExp, flags );
- }
-
- function firstDocumentLinkMatching( re, paren )
- {
- var x, i;
- for( i=0; i<document.links.length; i++ )
- if( (x = re.exec( document.links[i].href )) )
- return x[paren]; // should perhaps backtrack up to parent TR, get its
- // previous sibling and verify that its contentText == 'Buy this Book'
- }
-
- // AJAX callback returning the first <a href="..."> link to a page whose URL starts with `url'.
- // baseURL is prepended to the returned result, so passing "/search?" and "http://example.com"
- // might yield a link to "http://example.com/search?isbn=0596000480", if the page contained it.
- function firstLinkTo( url, baseURL )
- {
- return function( html, http )
- {
- return baseURL + unHTML(html.match( '<a(?:[^>]*) href=["\']?('+ quoteRegExp( url ) +'[^\'" >]*)' )[1]);
- };
- }
-
- function nextTagAfter( tag, content )
- {
- return function()
- {
- var tags = document.getElementsByTagName( tag ), i, node, isbn;
- for( i=0; i<tags.length; i++ )
- if( tags[i].innerHTML.match( content ) )
- for( j=tags[i].nextSibling; j=j.nextSibling; )
- if( (isbn = j.textContent.replace( /-/g, '' ).match( /[0-9X]{10}/i )) )
- return isbn[0];
- };
- }
-
- function nextSameTagAfter( tag, content )
- {
- return function()
- {
- var isbn, i, tags = document.getElementsByTagName( tag );
- for( i=0; i<tags.length-1; i++ )
- if( tags[i].innerHTML.match( content ) &&
- (isbn = tags[i+1].innerHTML.match( /[0-9X]{10}/i )) &&
- (isbn = checkISBN( isbn && isbn[0] )) )
- return isbn;
- };
- }
-
- function unHTML( html )
- {
- return html.replace( /&(amp|lt|gt|quot|apos|#(\d+));/g, function( match, character, code )
- {
- return { amp:'&', lt:'<', gt:'>', quot:'"', apos:'\'' }[character] || String.fromCharCode( code );
- });
- }
-
- function SEK( price ){ return price.replace( /:-|kr| /gi, '' ) +' SEK'; }
-
- // document.getElementById() on steroids (ask for several ids, and you get them back as an array)
- function $( ids, doc )
- {
- if( typeof ids == 'string' )
- return (doc || document).getElementById( ids );
- for( var i=0; i<ids.length; i++ )
- ids[i] = (doc || document).getElementById( ids[i] );
- return ids;
- }
-
- // price cache since last seen book, one day expiry time
- var last_isbn = PRO_getValue( 'last_isbn', '' );
- //PRO_setValue( 'last_run', '0' );
- var last_run = PRO_getValue( 'last_run', '0' );
- var last_prices = PRO_getValue( 'last_prices', '' );
- //alert( 'last_run:'+last_run+'\nsaved:\n\n' + last_prices );
-
- function getPrices( isbn )
- {
- var now = (new Date).getTime();
- //alert( isbn +':'+ last_isbn +'\n'+ (now-parseInt( last_run )) +'\n' + last_prices );
- if( (isbn != last_isbn) || (now-parseInt( last_run ) > 36e5) ||
- (last_prices.split( '\n' ).length != handlers.length) ) return false;
- return decodePrices( last_prices );
- }
-
- var prices = {};
- function updateCache( isbn, store, price )
- {
- var now = (new Date).getTime(), got = 0, i, h;
- if( (isbn != last_isbn) || (now - parseInt( last_run ) > 864e5) )
- prices = {};
- last_isbn = isbn;
- last_run = now.toString();
- prices[store] = price;
- for( i in prices ) got++;
- if( got == handlers.length )
- {
- //alert( encodePrices( prices ) );
- PRO_setValue( 'last_prices', last_prices = encodePrices( prices ) );
- PRO_setValue( 'last_isbn', isbn );
- PRO_setValue( 'last_run', last_run );
- }
- else
- ;//alert( got +'/' + handlers.length );
- }
-
- function decodePrices( stored )
- {
- var prices = {}, i, raw = (stored||'').split( '\n' );
- for( i=0; i<raw.length; i++ )
- {
- var data = raw[i].split( ':' );
- prices[data.shift()] = data.join( ':' );
- }
- return prices;
- }
-
- function encodePrices( prices )
- {
- var i, raw = [];
- for( i in prices )
- raw.push( i +':'+ prices[i] );
- return raw.join( '\n' );
- }
-
- function updatePrices( prices, isbn )
- {
- var id, node, price, data, errmsg =
- 'Oops! Either there are no books available,\\n' +
- 'or there is a parsing error due to changes\\n' +
- 'in to this website\\\'s page format.';
- for( id in prices )
- if( (node = document.getElementById( 'burro_'+id )) )
- {
- if( debug ) PRO_log( id +' price set to '+ prices[id] );
- data = (prices[id] || '').split( ':' );
- if( (price = data.shift()) )
- {
- node.firstChild.nodeValue = price;
- if( data.length )
- updateURL( id, data.join( ':' ) );
- }
- else
- node.innerHTML = '<a style="text-decoration:none;color:#00A;" href="javascript:alert(\''+ errmsg +'\');">none</a>';
- if( isbn )
- updateCache( isbn, id, price );
- }
- }
-
- function findHeader( headers, name )
- {
- var i, found;
- name = regexpify( name, 'i', 'quote' );
- for( i in headers )
- if( i.match( name ) )
- return headers[i];
- }
-
- function runQueries( isbn )
- {
- var j, request, callback, prices = debug ? false : getPrices( isbn );
- if( prices ) return updatePrices( prices ); // already cached
- for(var i=0; i<handlers.length; i++ )
- {
- var h = handlers[i];
- PRO_log('Query ' + h.id + ' for isbn ' + isbn);
- if( h.ajaxPrice != false )
- {
- if( debug )
- PRO_log( h.id +': '+ (h.ajaxMethod||'POST')+'( '+(h.ajaxURL||h.bookURL) + ' )' );
- /*
- request = { method:h.ajaxMethod||'POST', data:(h.ajaxData||'').replace( /%s/g, isbn ),
- onload:makeAjaxCallback( h, isbn ), url:(h.ajaxURL||h.bookURL).replace( /%s/g, isbn ) };
- if( h.ajaxHeaders ) request.headers = h.ajaxHeaders;
- if( (request.method == 'POST') && !findHeader( request.headers = request.headers || {}, 'Content-Type' ) )
- request.headers['Content-Type'] = 'application/x-www-form-urlencoded';
- PRO_xmlhttpRequest( request );
- */
- go(h, isbn);
- }
- }
- }
-
- function go(h, isbn)
- {
- var xmlhttp = PRO_xmlhttpRequest();
- var method = h.ajaxMethod || 'POST';
- var url = (h.ajaxURL||h.bookURL).replace( /%s/g, isbn );
- var data = (h.ajaxData||'').replace( /%s/g, isbn );
- var headers = h.ajaxHeaders;
-
- xmlhttp.open(method, url, true);
- /*
- if(method == 'POST' && !findHeader( headers || {}, 'Content-Type' ) )
- xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
- */
-
- if(method == 'POST') xmlhttp.send(data);
- else xmlhttp.send(null);
- xmlhttp.onreadystatechange = function(){
- if(xmlhttp.readyState == 4) makeAjaxCallback(h, isbn)(xmlhttp);
- }
- }
-
- function updateURL( id, url )
- {
- document.getElementById( 'burro_book_' + id ).href = url;
- }
-
- function makeAjaxCallback( handler, isbn)
- {
- var callback = handler.ajaxPrice;
- if(debug) PRO_log('Callback for ' + handler.name + ':' + (typeof callback));
- switch( typeof callback )
- {
- case 'function':
- if( !callback.exec )
- break; // callback is already our proper callback
- // fall-through -- it was a regexp:
-
- case 'string':
- callback = function( html, http )
- {
- var x = html.match( handler.ajaxPrice );
- var price = html.match( handler.ajaxPrice )[1].replace( / /g, '' );
- if( debug > 2 ) PRO_log( 'found raw '+ handler.id +'price '+ price );
- if( price ) price = unHTML( price );
- if( price && handler.priceFix ) price = handler.priceFix( price );
- return price;
- };
- break;
-
- case 'object': // array of string or regexp
- callback = function( html, http )
- {
- var i, price, regexps = handler.ajaxPrice;
- if(regexps.length){
- for( i=0; i<regexps.length; i++ )
- if( (price = html.match( regexps[i] )) )
- {
- price = price[1];
- if( debug > 2 ) PRO_log( 'found raw '+ handler.id +' price '+ price +' for regexp '+ regexps[i] );
- if( price && handler.priceFix ) price = handler.priceFix( price );
- return price;
- }
- } else {
- if( (price = html.match(handler.ajaxPrice)) )
- {
- price = price[1];
- if( price && handler.priceFix ) price = handler.priceFix( price );
- return price;
- }
- }
- };
- break;
-
- default:
- alert( 'Price handler for '+ handler.name +' (id '+ handler.id +
- ') is of illegal type '+ (typeof callback) +'! Ignoring.' );
- // fall-through:
-
- case 'boolean':
- callback = function(){};
- }
- return function( xmlHttpResponse )
- {
- if( debug ) with( xmlHttpResponse )
- PRO_log( 'Status ' + status+' '+statusText + ': '+ responseText.length +' bytes' );
- var failure = false, prices = {}, result = '', node, id, price;
- try {
- result = callback( xmlHttpResponse.responseText, xmlHttpResponse ) || '';
- } catch (e) {
- failure = true;
- if( debug )
- PRO_log( 'Failed to load or parse '+ handler.name +' (id '+ handler.id +'): ' +e );
-
- }
-
- //if( debug && handler.id == 'ecampus')
- PRO_log( 'Response from ' + handler.id + ':' + xmlHttpResponse.responseText );
-
-
- if( handler.updateURL )
- try {
- var url = handler.updateURL( xmlHttpResponse.responseText, xmlHttpResponse );
- if( url )
- updateURL( handler.id, url );
- } catch( e ) {}
- if( typeof result == 'string' ) // a price tag
- {
- if( url ) result += ':' + url; // a new book URL to link
- prices[handler.id] = result;
- }
- else if( typeof result == 'boolean' ) // availability info only
- {
- if( url ) result += ':' + url; // a new book URL to link
- prices[handler.id] = result ? 'available' : 'unavailable';
- }
- else
- prices = result;
- updatePrices( prices, isbn );
- };
- }
-
- function checkEAN( ean )
- {
- try {
- ean = (ean||'').replace( /-| | /gi, '' );
- if( ean.length != 13 ) return false;
- var checksum = 0;
- for( var i=0; i<12; i++ )
- checksum += ean.charAt(i) * (i&1 ? 3 : 1);
- checksum = (10 - (checksum % 10)) % 10;
- if( ean.charAt(12) == checksum )
- return ean;
- else
- {
- if( debug ) PRO_log( 'EAN '+ean+ ' failed checksum.' );
- return false;
- }
- }
- catch (e)
- {
- if( debug ) PRO_log( 'checkEAN: '+ e );
- return false;
- }
- }
-
- function checkISBN( isbn )
- {
- try {
- isbn = (isbn||'').toLowerCase().replace( /-| | /g, '' );
- if( isbn.length == 13) return true;
- if( isbn.length != 10 ) return false;
- var checksum = 0;
- for( var i=0; i<9; i++ )
- if( isbn.charAt(i) == 'x' )
- checksum += 10 * (i+1);
- else
- checksum += isbn.charAt(i) * (i+1);
- checksum = checksum % 11;
- if( checksum == 10 ) checksum = 'x';
- if( isbn.charAt(9) == checksum )
- return isbn;
- else
- {
- if( debug ) PRO_log( 'ISBN '+isbn+ ' failed checksum.' );
- return false;
- }
- }
- catch (e)
- {
- if( debug ) PRO_log( 'checkISBN: '+ e );
- return false;
- }
- }
-
- function dom_createLink( url, txt, title, id )
- {
- var a = document.createElement( 'a' );
- if( id ) a.id = id;
- a.setAttribute( 'target', '_top' );
- a.setAttribute( 'href', url );
- with( a.style )
- {
- color = '#00A';
- textDecoration = 'none';
- fontWeight = 'bold';
- }
- if( title ) a.setAttribute( 'title', title );
- a.appendChild( document.createTextNode( txt ) );
- return a;
- }
-
- function addSite( url, title, loc_id )
- {
- var tr = document.createElement( 'div' );
- var td_left = document.createElement( 'span' );
- var a = dom_createLink( url, title, title+' Search', 'burro_book_'+loc_id );
- td_left.style.paddingLeft = '5px';
- td_left.appendChild( a );
- tr.appendChild( td_left );
-
- var td_right = document.createElement( 'span' );
- td_right.innerHTML = 'fetching';
- td_right.style.paddingRight = '5px';
- td_right.id = 'burro_' + loc_id;
- tr.appendChild( td_right );
-
- if( document.all ) // IE only
- {
- tr.style.position = 'relative';
- td_right.style.textAlign = 'right';
- td_right.style.position = 'absolute';
- td_right.style.left = '10em';
- td_right.style.width = '4em';
- }
- else // other browsers
- {
- tr.style.display = 'table-row';
- td_left.style.display = 'table-cell';
- td_right.style.display = 'table-cell';
- }
- return tr;
- }
-
- function str2xml( strXML )
- {
- if( window.ActiveXObject )
- {
- var domdoc = new ActiveXObject( 'Microsoft.XMLDOM' );
- domdoc.async = 'false';
- domdoc.loadXML( strXML );
- return domdoc;
- }
- else
- {
- var objDOMParser = new DOMParser();
- return objDOMParser.parseFromString( strXML, 'text/xml' );
- }
- }
-
- function int2money( cents )
- {
- var money = '$'
- if( cents < 100 )
- money = money + '0.';
- else
- money = money + Math.floor( cents/100 ) + '.';
- cents = cents % 100;
- if( cents < 10 )
- money = money + '0';
- money = money + cents;
- return money;
- }
-
- var Drag = function(){ this.init.apply( this, arguments ); };
-
- Drag.fixE = function( e )
- {
- if( typeof e == 'undefined' ) e = window.event;
- if( typeof e.layerX == 'undefined' ) e.layerX = e.offsetX;
- if( typeof e.layerY == 'undefined' ) e.layerY = e.offsetY;
- return e;
- };
-
- Drag.prototype.init = function( handle, dragdiv )
- {
- this.div = dragdiv || handle;
- this.handle = handle;
- if( isNaN(parseInt(this.div.style.right )) ) this.div.style.right = '0px';
- if( isNaN(parseInt(this.div.style.bottom)) ) this.div.style.bottom = '0px';
- this.onDragStart = function(){};
- this.onDragEnd = function(){};
- this.onDrag = function(){};
- this.onClick = function(){};
- //this.mouseDown = addEventHandler( this.handle, 'mousedown', this.start, this );
- };
-
- Drag.prototype.start = function( e )
- {
- // this.mouseUp = addEventHandler( this.handle, 'mouseup', this.end, this );
- e = Drag.fixE( e );
- this.started = new Date();
- var y = this.startY = parseInt(this.div.style.bottom);
- var x = this.startX = parseInt(this.div.style.right);
- this.onDragStart( x, y );
- this.lastMouseX = e.clientX;
- this.lastMouseY = e.clientY;
- //this.documentMove = addEventHandler( document, 'mousemove', this.drag, this );
- this.documentStop = addEventHandler( document, 'mouseup', this.end, this );
- if( e.preventDefault ) e.preventDefault();
- return false;
- };
-
- Drag.prototype.drag = function( e )
- {
- e = Drag.fixE( e );
- var ey = e.clientY;
- var ex = e.clientX;
- var y = parseInt(this.div.style.bottom);
- var x = parseInt(this.div.style.right );
- var nx = x - ex + this.lastMouseX;
- var ny = y - ey + this.lastMouseY;
- this.div.style.right = nx + 'px';
- this.div.style.bottom = ny + 'px';
- this.lastMouseX = ex;
- this.lastMouseY = ey;
- this.onDrag( nx, ny );
- if( e.preventDefault ) e.preventDefault();
- return false;
- };
-
- Drag.prototype.end = function()
- {
- //removeEventHandler( document, 'mousemove', this.documentMove );
- removeEventHandler( document, 'mouseup', this.documentStop );
- var time = (new Date()) - this.started;
- var x = parseInt(this.div.style.right), dx = this.startX - x;
- var y = parseInt(this.div.style.bottom), dy = this.startY - y;
- this.onDragEnd( x, y, dx, dy, time );
- if( (dx*dx + dy*dy) < (4*4) && time < 1e3 )
- this.onClick( x, y, dx, dy, time );
- };
-
- function removeEventHandler( target, eventName, eventHandler )
- {
- if( target.addEventListener )
- target.removeEventListener( eventName, eventHandler, true );
- else if( target.attachEvent )
- target.detachEvent( 'on' + eventName, eventHandler );
- }
-
- function addEventHandler( target, eventName, eventHandler, scope )
- {
- var f = scope ? function(){ eventHandler.apply( scope, arguments ); } : eventHandler;
- if( target.addEventListener )
- target.addEventListener( eventName, f, true );
- else if( target.attachEvent )
- target.attachEvent( 'on' + eventName, f );
- return f;
- }
-
- function burro( location, isbn )
- {
- if( debug > 1 ) PRO_log( 'adding burro' );
- var handle = document.createElement( 'div' );
- var root = document.createElement( 'div' );
- var box = document.createElement( 'div' ), i, h;
- with( root.style )
- {
- position = 'absolute';
- top = right = '15px';
- }
- handle.style.padding = '4px';
- handle.title = 'Click title to expand, collapse or drag';
- with( box.style )
- {
- position = 'relative';
- zIndex = '1000';
-
- backgroundColor = '#FFC';
- border = '1px solid orange';
- padding = '0px';
- textAlign = 'left';
- font = '8pt sans-serif';
- width = '240px';
- marginBottom = '15px';
-
- opacity = '0.93';
- filter = 'alpha(opacity=90)';
- }
-
- var carrot = document.createElement( 'img' );
- carrot.style.top = '-10px';
- carrot.src = Icons.carrotRight;
- carrot.id = 'hide_show_carrot';
- handle.appendChild( carrot );
-
- var title_image = document.createElement( 'img' );
- title_image.style.marginLeft = '6px';
- title_image.src = Icons.title;
- handle.appendChild( title_image );
-
- var close = document.createElement( 'img' );
- close.src = Icons.close;
- with( close.style )
- {
- position = 'absolute';
- right = '3px';
- top = '3px';
- margin = '2px';
- width = '12px';
- height = '12px';
- backgroundColor = '#FFB';
- border = 'none';
- lineHeight = '8px';
- textAlign = 'center';
- }
- close.setAttribute( 'title', 'Click to remove' );
- addEventHandler( close, 'click', function(){ document.body.removeChild( root ); } );
- handle.appendChild( close );
-
- var about = document.createElement( 'a' );
- var about_img = document.createElement( 'img' );
- about_img.src = Icons.about;
- about_img.style.border = 'none';
- about.appendChild( about_img );
- with( about.style )
- {
- position = 'absolute';
- right = '18px';
- top = '3px';
- margin = '2px';
- width = '12px';
- height = '12px';
- backgroundColor = '#FFB';
- lineHeight = '12px';
- textAlign = 'center';
- textDecoration = 'none';
- }
- about.title = 'OverStimulate / modified by Reify and Johan Sundstr├╢m';
- about.href = 'http://overstimulate.com/articles/2005/04/24/greasemonkey-book-burro-find-cheap-books';
- handle.appendChild( about );
- box.appendChild( handle );
-
- var table = document.createElement( 'div' );
- with( table.style )
- {
- marginTop = '1px';
- marginBottom = '3px';
- padding = '0';
- width = '100%';
- font = '10pt sans-serif';
- display = 'none';
- }
- table.id = 'bookburro-pricesTable';
- for( i=0; i<handlers.length; i++ )
- {
- h = handlers[i];
- table.appendChild( addSite( h.bookURL.replace( /%s/g, isbn ), h.name, h.id ) );
- }
- box.appendChild( table );
-
- var zip = function()
- {
- box.opened = !box.opened;
- var pricesTable = document.getElementById( 'bookburro-pricesTable' );
- var carrot = document.getElementById( 'hide_show_carrot' );
- if( box.opened ) // pricesTable.style.display == 'none'
- {
- if( !hasFetched ) runQueries( isbn );
- hasFetched = true;
- pricesTable.style.display = document.all ? 'block' : 'table';
- carrot.src = Icons.carrotDown;
- }
- else
- {
- pricesTable.style.display = 'none';
- carrot.src = Icons.carrotRight;
- }
- };
- //addEventHandler( box, 'click', zip );
- root.appendChild( box );
- document.body.appendChild( root );
- //handle.drag = new Drag( handle, box );
- //handle.drag.onClick = zip;
- zip();
- if( debug > 1 ) PRO_log( 'added burro' );
- }
-
- function init()
- {
- var i, h, getISBN, isbn;
- for( i=0; i<handlers.length; i++ )
- {
- h = handlers[i];
- if( h.hostname && location.hostname.match( h.hostname ) )
- try {
- if( debug ) PRO_log( h.name +' matched at '+ location.hostname );
- getISBN = h.getISBN || /isbn[\/=]([0-9X]{10})(&|\?|\.|$)/i || /ISBN[\/=]([0-9X]{10})(&|\?|\.|$)/i;
- switch( typeof getISBN )
- {
- case 'string':
- getISBN = new RegExp( getISBN );
- // fall-through
- case 'function':
- case 'object':
- if( getISBN.exec ) // a regexp
- {
- var rx = getISBN;
- getISBN = function(){ return location.href.match( rx )[1]; };
- }
- isbn = getISBN();
- break;
-
- default:
- alert( 'getISBN handler for '+ h.name +' (id '+ h.id +
- ') is of illegal type '+ (typeof getISBN) +'! Ignoring.' );
- continue;
- }
- if( (isbn = checkISBN( isbn )) ){
- burro( h.id, isbn );
- }
- else if( debug )
- PRO_log( 'Failed to find ISBN for '+ h.name +' (id '+ h.id +')' );
- } catch (e) { if( debug ) PRO_log( e ); }
- }
- }
-
- // addEventHandler(document, 'load', init);
- init();
-